#####################################################
# FlatBuffers.cmake - FlatBuffers 集成模块
# 
# 提供flatbuffers的查找、配置和代码生成功能
# 自动处理fbs文件编译和目标依赖关系
#####################################################

# 选项：是否启用flatbuffers支持
option(ENABLE_FLATBUFFERS "启用FlatBuffers支持" ON)

# 全局变量
set(FLATBUFFERS_ENABLED FALSE CACHE INTERNAL "FlatBuffers是否可用")
set(FLATBUFFERS_GENERATED_TARGET "" CACHE INTERNAL "FlatBuffers生成文件目标")
set(FLATBUFFERS_GENERATED_HDRS "" CACHE INTERNAL "FlatBuffers生成的头文件列表")

#####################################################
# 设置flatbuffers集成
# 查找flatbuffers库，配置编译环境
#####################################################
function(setup_flatbuffers)
    if(NOT ENABLE_FLATBUFFERS)
        message(STATUS "FlatBuffers: 已通过 ENABLE_FLATBUFFERS=OFF 禁用")
        return()
    endif()

    # 尝试查找flatbuffers
    find_package(FlatBuffers QUIET)
    
    if(FlatBuffers_FOUND)
        message(STATUS "FlatBuffers: 已找到系统安装的flatbuffers")
        message(STATUS "  版本: ${FlatBuffers_VERSION}")
        message(STATUS "  包含目录: ${FlatBuffers_INCLUDE_DIRS}")
        message(STATUS "  库文件: ${FlatBuffers_LIBRARIES}")
        message(STATUS "  编译器: ${FlatBuffers_FLATC_EXECUTABLE}")
        
        # 设置到全局作用域
        set(FlatBuffers_INCLUDE_DIRS ${FlatBuffers_INCLUDE_DIRS} CACHE INTERNAL "FlatBuffers包含目录")
        set(FlatBuffers_LIBRARIES ${FlatBuffers_LIBRARIES} CACHE INTERNAL "FlatBuffers库文件")
        set(FlatBuffers_FLATC_EXECUTABLE ${FlatBuffers_FLATC_EXECUTABLE} CACHE INTERNAL "FlatBuffers编译器")
        
        set(FLATBUFFERS_ENABLED TRUE CACHE INTERNAL "FlatBuffers是否可用")
        
    else()
        # 尝试从third_party子项目查找
        if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/third_party/flatbuffers/CMakeLists.txt")
            message(STATUS "FlatBuffers: 使用third_party/flatbuffers子项目")
            add_subdirectory(third_party/flatbuffers)
            
            # 检查子项目是否成功创建了目标
            if(TARGET flatbuffers::libflatbuffers)
                set(FLATBUFFERS_ENABLED TRUE CACHE INTERNAL "FlatBuffers是否可用")
                
                # 设置变量以兼容find_package结果
                get_target_property(FlatBuffers_INCLUDE_DIRS flatbuffers::libflatbuffers INTERFACE_INCLUDE_DIRECTORIES)
                set(FlatBuffers_LIBRARIES flatbuffers::libflatbuffers)
                
                # 查找flatc可执行文件
                find_program(FlatBuffers_FLATC_EXECUTABLE flatc
                    PATHS ${CMAKE_CURRENT_SOURCE_DIR}/third_party/flatbuffers/bin
                    NO_DEFAULT_PATH
                )
                if(NOT FlatBuffers_FLATC_EXECUTABLE)
                    find_program(FlatBuffers_FLATC_EXECUTABLE flatc)
                endif()
                
                # 设置到全局作用域
                set(FlatBuffers_INCLUDE_DIRS ${FlatBuffers_INCLUDE_DIRS} CACHE INTERNAL "FlatBuffers包含目录")
                set(FlatBuffers_LIBRARIES ${FlatBuffers_LIBRARIES} CACHE INTERNAL "FlatBuffers库文件")
                set(FlatBuffers_FLATC_EXECUTABLE ${FlatBuffers_FLATC_EXECUTABLE} CACHE INTERNAL "FlatBuffers编译器")
                
                message(STATUS "  编译器: ${FlatBuffers_FLATC_EXECUTABLE}")
            else()
                message(WARNING "FlatBuffers: third_party/flatbuffers子项目未能创建flatbuffers::libflatbuffers目标")
            endif()
        else()
            message(STATUS "FlatBuffers: 未找到flatbuffers库，flatbuffers功能将被禁用")
        endif()
    endif()
    
    if(FLATBUFFERS_ENABLED)
        message(STATUS "FlatBuffers: 已启用flatbuffers支持")
    else()
        message(STATUS "FlatBuffers: flatbuffers支持已禁用")
    endif()
endfunction()

#####################################################
# 生成flatbuffers文件
# 查找所有fbs文件并生成对应的C++代码和结构体
#####################################################
function(generate_flatbuffers_files)
    if(NOT FLATBUFFERS_ENABLED)
        return()
    endif()
    
    if(NOT FlatBuffers_FLATC_EXECUTABLE)
        message(FATAL_ERROR "FlatBuffers: 未找到flatc编译器")
        return()
    endif()

    message(STATUS "FlatBuffers: 开始生成flatbuffers文件")
    
    # 查找所有fbs文件
    file(GLOB_RECURSE FLATBUFFER_FILES "${CMAKE_CURRENT_SOURCE_DIR}/schemas/*.fbs")
    
    if(NOT FLATBUFFER_FILES)
        message(STATUS "FlatBuffers: 未找到fbs文件")
        return()
    endif()
    
    message(STATUS "FlatBuffers: 找到 ${CMAKE_CURRENT_LIST_LENGTH} 个fbs文件: ${FLATBUFFER_FILES}")
    
    # 查找Python3
    find_package(Python3 COMPONENTS Interpreter)
    if(NOT Python3_Interpreter_FOUND)
        message(WARNING "FlatBuffers: 未找到Python3，将跳过结构体生成")
        set(SKIP_STRUCT_GENERATION TRUE)
    else()
        set(SKIP_STRUCT_GENERATION FALSE)
        message(STATUS "FlatBuffers: 找到Python3: ${Python3_EXECUTABLE}")
    endif()
    
    # 生成flatbuffer文件和结构体
    set(GENERATED_HDRS)
    set(GENERATED_STRUCT_HDRS)
    
    foreach(FBS_FILE ${FLATBUFFER_FILES})
        get_filename_component(FBS_NAME ${FBS_FILE} NAME_WE)
        get_filename_component(FBS_DIR ${FBS_FILE} DIRECTORY)
        
        set(GENERATED_HDR "${CMAKE_CURRENT_BINARY_DIR}/${FBS_NAME}_generated.h")
        set(GENERATED_STRUCT_HDR "${CMAKE_CURRENT_BINARY_DIR}/${FBS_NAME}_structs.h")
        
        list(APPEND GENERATED_HDRS ${GENERATED_HDR})
        
        # 生成FlatBuffer头文件
        add_custom_command(
            OUTPUT ${GENERATED_HDR}
            COMMAND ${FlatBuffers_FLATC_EXECUTABLE} 
                --cpp -o ${CMAKE_CURRENT_BINARY_DIR}
                ${FBS_FILE}
            DEPENDS ${FBS_FILE}
            COMMENT "FlatBuffers: 正在生成 ${FBS_NAME}_generated.h"
            VERBATIM
        )
        
        message(STATUS "FlatBuffers: 将生成 ${FBS_NAME}_generated.h")
        
        # 生成C++结构体头文件（如果有Python3）
        if(NOT SKIP_STRUCT_GENERATION)
            list(APPEND GENERATED_STRUCT_HDRS ${GENERATED_STRUCT_HDR})
            
            set(STRUCT_GENERATOR_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/flatbuffer_struct_generator.py")
            if(NOT EXISTS ${STRUCT_GENERATOR_SCRIPT})
                set(STRUCT_GENERATOR_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/flatbuffer_struct_generator.py")
                message(ERROR "FlatBuffers: 未找到flatbuffer_struct_generator.py")
            endif()
            
            add_custom_command(
                OUTPUT ${GENERATED_STRUCT_HDR}
                COMMAND ${Python3_EXECUTABLE} 
                    ${STRUCT_GENERATOR_SCRIPT}
                    ${FBS_FILE}
                    ${GENERATED_STRUCT_HDR}
                DEPENDS ${FBS_FILE} ${STRUCT_GENERATOR_SCRIPT}
                COMMENT "FlatBuffers: 正在生成 ${FBS_NAME}_structs.h"
                VERBATIM
            )
            
            message(STATUS "FlatBuffers: 将生成 ${FBS_NAME}_structs.h")
        endif()
    endforeach()
    
    # 创建包含所有生成文件的目标
    set(ALL_GENERATED_FILES ${GENERATED_HDRS})
    if(NOT SKIP_STRUCT_GENERATION)
        list(APPEND ALL_GENERATED_FILES ${GENERATED_STRUCT_HDRS})
    endif()
    
    add_custom_target(flatbuffer_generated 
        DEPENDS ${ALL_GENERATED_FILES}
        COMMENT "FlatBuffers: 生成所有flatbuffer文件"
    )
    
    # 设置全局变量
    set(FLATBUFFERS_GENERATED_TARGET flatbuffer_generated CACHE INTERNAL "FlatBuffers生成文件目标")
    set(FLATBUFFERS_GENERATED_HDRS ${GENERATED_HDRS} CACHE INTERNAL "FlatBuffers生成的头文件列表")
    set(FLATBUFFERS_GENERATED_STRUCT_HDRS ${GENERATED_STRUCT_HDRS} CACHE INTERNAL "FlatBuffers生成的结构体头文件列表")
    
    message(STATUS "FlatBuffers: 生成目标 '${FLATBUFFERS_GENERATED_TARGET}' 已创建")
endfunction()

#####################################################
# 为目标添加flatbuffers支持
# target_name: 目标名称
# 自动添加flatbuffers依赖、包含目录和生成文件依赖
#####################################################
function(add_flatbuffers_to_target target_name)
    if(NOT FLATBUFFERS_ENABLED)
        return()
    endif()
    
    # 添加flatbuffers库依赖
    target_link_libraries(${target_name} PRIVATE ${FlatBuffers_LIBRARIES})
    
    # 添加包含目录
    if(FlatBuffers_INCLUDE_DIRS)
        target_include_directories(${target_name} PRIVATE ${FlatBuffers_INCLUDE_DIRS})
    endif()
    
    # 添加生成文件目录
    target_include_directories(${target_name} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
    
    # 添加生成文件依赖
    if(FLATBUFFERS_GENERATED_TARGET)
        add_dependencies(${target_name} ${FLATBUFFERS_GENERATED_TARGET})
    endif()
    
    message(STATUS "FlatBuffers: 已为目标 '${target_name}' 添加flatbuffers支持")
endfunction()

#####################################################
# 获取flatbuffers相关的编译选项
# 返回需要添加到COMMON_PRIVATE_DEPS的依赖列表
#####################################################
function(get_flatbuffers_deps output_var)
    set(deps "")
    if(FLATBUFFERS_ENABLED AND FlatBuffers_LIBRARIES)
        list(APPEND deps ${FlatBuffers_LIBRARIES})
    endif()
    set(${output_var} ${deps} PARENT_SCOPE)
endfunction()

#####################################################
# 获取flatbuffers相关的包含目录
# 返回需要添加到COMMON_INCLUDE_DIRS的目录列表
#####################################################
function(get_flatbuffers_include_dirs output_var)
    set(dirs "")
    if(FLATBUFFERS_ENABLED)
        if(FlatBuffers_INCLUDE_DIRS)
            list(APPEND dirs ${FlatBuffers_INCLUDE_DIRS})
        endif()
        list(APPEND dirs ${CMAKE_CURRENT_BINARY_DIR})
    endif()
    set(${output_var} ${dirs} PARENT_SCOPE)
endfunction()

#####################################################
# 检查目标是否需要flatbuffers支持
# 根据目标名称判断是否为flatbuffers相关的demo
#####################################################
function(target_needs_flatbuffers target_name output_var)
    set(needs_flatbuffers FALSE)
    
    if(FLATBUFFERS_ENABLED)
        # 检查是否为flatbuffers相关的目标
        # if(target_name MATCHES ".*flatbuffer.*" OR 
        #    target_name MATCHES ".*table_struct_attributes.*" OR
        #    target_name STREQUAL "demos_flatbuffer_serializer_test" OR
        #    target_name STREQUAL "demos_flatbuffer_serializer_complete_test" OR
        #    target_name STREQUAL "demos_table_struct_attributes_demo")
            set(needs_flatbuffers TRUE)
        # endif()
    endif()
    
    set(${output_var} ${needs_flatbuffers} PARENT_SCOPE)
endfunction()
